module Math where

import Data.Set
import Prelude hiding (filter, map, null, and, or, elem, id)

infix  4 ⊂, ⊃, ⊆, ⊇
infixr 3 ∩
infixr 2 ∪
infixl 4 →
infixr 4 ←
infix  2 ↔
infixr 5 !

-- PROBLÉMÁK:
--    member 3 (fromList [1..])

-- kell: sorozatok halmaza ! + egyebek ami nem ord..

(∩) x y = intersection x y
(∪) x y = union x y
(×) xs ys = fold (\a b -> (map (\y -> (a,y)) ys) ∪ b) empty xs

(⊂) x y = isProperSubsetOf x y
(⊃) x y = y ⊂ x
(⊆) x y = isSubsetOf x y
(⊇) x y = y ⊆ x

and =  fold (&&) True
or =  fold (||) False
(∃) p = or . map p
(∀) p = and . map p
x ∈ xs = member x xs
xs ∋ x = member x xs

(→) a b = not a || (a && b)
(←) = flip (→)
(↔) a b = (a → b) && (a ← b)
(∏) = product
(∑) = sum

nat = [1..]
nat0 = [0..]

-- relációk --
--data Rel = (Ord a) => Set a

-- data relation A×B... ??
-- Konvenció: jelölje xs a relációt

-- értelmezési tartomány
domain xs = map (\(a,_) -> a) xs --fromList [a | (a,b) <- elems xs]
-- értékkészlet
range xs = map (\(_,b) -> b) xs --fromList [b | (a,b) <- elems xs]

-- inverz
invert xs = map (\(a,b) -> (b,a)) xs

-- kép
img xs ys = range ( xs ! ys ) -- todo chk
imgMem xs y = range ( filter (\(x,_) -> x == y) xs ) -- todo chk

-- inverz kép
invImg xs ys = img (invert xs) ys -- todo chk
invMem xs y = imgMem (invert xs) y -- todo chk

-- xs leszűkítése h-ra
xs ! h = filter (\(x,_) -> x ∈ h) xs

-- őskép -- todo naming
oskep xs ys = filter (\a -> (imgMem xs a) ⊆ ys) (domain xs) -- todo chk
--[a | a<-(elems $ domain xs), (imgMem xs a) ⊆ ys]

-- kompozíció
q ° p = fromList [(a,d) | (a,b) <- elems p, (c,d) <- elems q, b == c] 
--HUH na most jön a nemdet: q °° p = map (\(a,b) -> pffffff) (filter (\(_,b) -> b ∈ domain q) p) 
q °! p = fromList [(a,d) | (a,b) <- elems p, (c,d) <- elems q, a == b, imgMem p a ⊆ domain q]

-- identikus
id xs = map (\x -> (x,x)) xs

-- lezártja : todo
{-lezar xs a b = -- rel ⊆ a×b
  where
    dLezart = filter -}

-- korlátos lezártja

-- igazsághalmaz, megszorított

ighalm xs = oskep xs (singleton True)
ighalm' xs = invMem xs True

xs `megsz` pi = xs ! jippi ∪ jippiMinDxs
  where
    jippi = ighalm pi
    jippiMinDxs = id (jippi \\ (domain xs)) --fromList ( [ (a,a) | a <- (jippi \\ (domain xs))] )

-- helper --
f `on` g = \x y -> f (g x) (g y)

